import { get } from '@ajax/axios'
import { isServer } from '@config/env'
import WCache from '@utils/cache'
import { CATCH_KEY_DETAIL_DATA } from './cacheKey'

class BaseModel {
 
  public _id: string = ''

  // 加载所有的数据
  static loadAllApi: string
  // 所有数据的缓存KEY
  static LOAD_ALL_CACHE_KEY: string
  // 加载所有类型
  static loadTypesApi: string
  // 所有类型的缓存KEY
  static LOAD_TYPES_KEY: string
  // 加载列表的API
  static loadListApi: string
  // 加载详情的 API
  static loadDetailApi: string

  // 根据数据设置对象并获取
  public static instance(json: object) {
    if (isServer) {
      return json
    }
    const model = new this()
    model.setDataWithJson(json)
    return model
  }

  /**
   * JSON转模型
   * @param json json数据
   */
  setDataWithJson(json: {}) {
    Object.assign(this, json)
  }

  /**
   * 通过键值获取对象
   * @param keys 键值字符串(以空格做区分)
   */
  getJson(keys: string): object {
    const arr = keys.split(' ')
    const obj = {}
    arr.forEach((key: string) => {
      (obj as any)[key] = (this as any)[key]
    })
    return obj
  }

  /**
   * 数组转模型
   * @param arr 数组
   */
  static modelsWithArr<T extends BaseModel>(arr: object[]): Array<T> {
    return arr.map((json: object) => {
      const model = this.instance(json) as T
      return model
    })
  }

  /**
   * 加载所有的数据
   * @param query 请求参数
   * @param toModel 是否转成模型
   */
  static async loadAllModel(query: Object = {}, cache = true) {
    return await this.cacheData(() => {
      return get<Object[]>(this.loadAllApi, {
        ...query
      })
    }, this.LOAD_ALL_CACHE_KEY, cache)
  }

  /**
   * 加载所有类型
   * @param query 其他参数
   * @param cache 是否缓存
   */
  static async loadTypes(query: Object = {}, cache = true) {
    return await this.cacheData(() => {
      return get<Object[]>(this.loadTypesApi, {
        ...query
      })
    }, this.LOAD_TYPES_KEY, cache)
  }

  /**
   * 加载列表数据
   * @param query 参数
   */
  static async loadList(query: Object = {}) {
    return get<any>(this.loadListApi, {
      ...query
    })
  }

  static async getDetail(id: string, cache: boolean = true) {
    const key = `${CATCH_KEY_DETAIL_DATA}-id`
    return await this.cacheData(() => {
      return get<Object[]>(`${this.loadDetailApi}${id}`)
    }, key, cache)
  }

  /**
   * 缓存数据
   * @param asyncFunc 异步方法
   * @param key 键值
   */
  static async cacheData(asyncFunc: Function, key: string, cache: boolean) {
    if (!isServer && key && cache) {
      const data = WCache.get(key)
      if (data) {
        return data
      }
    }
    const data = await asyncFunc()
    if (!isServer ) {
      WCache.set(key, data)
    }
    return data
  }
}

export default BaseModel